/**
 * 封装nft相关的方法
 */

import {ethers} from 'ethers';
import abi from '../abis/nft.json';
import axios from 'axios';
import {market_address, my_nft_address} from "@/config/contract"

// 前端程序从浏览器可以获得provider
let provider = new ethers.BrowserProvider(window.ethereum)


// 构建合约实例
const contract = new ethers.Contract(my_nft_address, abi, await provider.getSigner());

// 获取账户地址余额（nft个数）
export async function balanceOf(
    address) {
    const result = await contract.balanceOf(address);
    return Number(result);
}

// owner的第index个nftId
export async function tokenOfOwnerByIndex(owner, index) {
    return await contract.tokenOfOwnerByIndex(owner, index);
}

// 根据nftId查询nft元数据的URI
export async function tokenURI(tokenId) {
    return await contract.tokenURI(tokenId)
}

// 从元数据位置中提取出，我们定义的metadata
export async function getMetadata(tokenId) {
    const result = await contract.tokenURI(tokenId);
    //axios.get(result)等价于在浏览器访问result
    const response = await axios.get(result);
    return {
        title: response.data.title,
        description: response.data.description,
        imageURL: response.data.image,
    }
}

//查询某个用户的NFT
export async function tokensOfOwner(address){
    const balance = await balanceOf(address)
    if(balance === 0){
        return []
    }else {
        const res = []
        for (let i = 0; i < balance; i++) {
            res.push(tokenOfOwnerByIndex(address,i))
        }
        return Promise.all(res)
    }
}

//查询用户NFT的tokenURI
export async function getTokenURI(address) {
    const id = await tokensOfOwner(address)
    if(id.length === 0){
        return null
    }else {
        const res = []
        for (let i = 0; i <id.length; i++) {
            res.push(tokenURI(id[i]))
        }
        return Promise.all(res)
    }
}

//查询某账户的metaData
export async function getMetadataOfOwner(address) {
    const uri = await getTokenURI(address)
    if(uri.length === 0){
        return null
    }else {
        const res = []
        for (let i = 0; i < uri.length; i++) {
            const metadata = (await axios.get(uri[i])).data
            res.push(
                {
                    title: metadata.title,
                    description: metadata.description,
                    imageURL: metadata.image,
                }
            )
        }
        return res
    }
}
export async function placeOrder(
    _seller,
    _tokenId,
    price
){
    return await contract["safeTransferFrom(address,address,uint256,bytes)"](
        _seller, market_address, _tokenId, toBytes(price));
}

function toBytes(num) {
    const result = new Uint8Array(32);
    const bigNum = BigInt(num*10**18);

    for (let i = 0; i < 32; i++) {
        const byteValue = Number(bigNum / (2n ** (8n * BigInt(31 - i))) % 256n);
        result[i] = byteValue;
    }
    return result;
}
